package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.message.NewsAutoScanConstants;
import com.heima.common.constants.message.WmNewsMessageConstants;
import com.heima.common.constants.wemedia.WemediaConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.WmThreadLocalUtils;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.vos.WmNewsVo;
import com.heima.model.wmUser.pojos.WmMaterial;
import com.heima.model.wmUser.pojos.WmUser;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@Slf4j
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {
    @Value("${file.oss.web-site}")
    private String webSite;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Autowired
    private WmNewsMapper wmNewsMapper;

    /**
     * 分页带条件查询自媒体文章列表
     */
    @Override
    public ResponseResult findNewsByPage(WmNewsPageReqDto dto) {
        dto.checkParam();
        //判断当前用户的登录信息
        WmUser user = WmThreadLocalUtils.getUser();
        if (user == null || user.getId() == null) {
            CustomException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer uid = user.getId();
        //获取分页查询的对象
        Page<WmNews> page = new Page<>(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(WmNews::getUserId, uid);
        wrapper.eq(dto.getStatus() != null, WmNews::getStatus, dto.getStatus());
        wrapper.ge(dto.getBeginPubDate() != null, WmNews::getPublishTime, dto.getBeginPubDate());
        wrapper.le(dto.getEndPubDate() != null, WmNews::getPublishTime, dto.getBeginPubDate());
        wrapper.eq(dto.getChannelId() != null, WmNews::getChannelId, dto.getChannelId());
        wrapper.like(StringUtils.isNotBlank(dto.getKeyword()), WmNews::getTitle, dto.getKeyword());
        wrapper.orderByDesc(WmNews::getCreatedTime);
        //执行分页查询
        IPage<WmNews> iPage = page(page, wrapper);
        PageResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), iPage.getTotal(), iPage.getRecords());
        result.setHost(webSite);
        return result;
    }

    /**
     * 自媒体文章-发布、修改、保存草稿
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseResult submit(WmNewsDto wmNewsDto) {
        //参数校验
        if (wmNewsDto == null || StringUtils.isBlank(wmNewsDto.getContent())) {
            CustomException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        //检查文章状态
        Short status = wmNewsDto.getStatus();//0表示存入草稿箱，1表示提交待审核
        if (status == null) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "当前文章状态异常!!!");
        }
        //获取登录状态
        WmUser user = WmThreadLocalUtils.getUser();
        if (user == null || user.getId() == null) {
            CustomException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer uid = user.getId();
        //拷贝属性
        WmNews wmNews = new WmNews();
        //获取封面图片，将其转换成字符串类型
        BeanUtils.copyProperties(wmNewsDto, wmNews);
        //如果type的属性为-1，将其设置为null，避免保存出错
        if (wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {
            wmNews.setType(null);
        }
        List<String> headImages = wmNewsDto.getImages();
        if (CollectionUtils.isNotEmpty(headImages)) {
            String images = headImages.stream()
                    .map(img -> img.replaceAll(webSite, ""))
                    .collect(Collectors.joining(","));
            //将字符串类型的封面图片存入wmNews中
            wmNews.setImages(images);
        }
        wmNews.setUserId(uid);
        //获取文章内容的url集合
        List<String> urlLists = getUrlLists(wmNews);
        //保存或修改文章
        saverOrUpdate(wmNews, wmNewsDto);
        /*//如果不是提交审核，则直接返回结果
        if (status == 0) {
            return ResponseResult.okResult();
        }*/

        //执行添加封面图片与素材的关联操作的操作
        if (CollectionUtils.isNotEmpty(urlLists) && CollectionUtils.isNotEmpty(headImages)) {
            addNewsMaterialByBucketForCover(urlLists, wmNews, wmNewsDto);
        }
        //执行添加内容图片的操作
        if (CollectionUtils.isNotEmpty(urlLists)) {
            addNewsMaterialByBucket(urlLists, wmNews.getId(), WemediaConstants.WM_IMAGE_REFERENCE);
        }

        //Kafaka发送消息
        HashMap<String, Integer> map = new HashMap<>();
        map.put("NewId", wmNews.getId());
        kafkaTemplate.send(NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_TOPIC, JSON.toJSONString(map));
        return ResponseResult.okResult();
    }

    /**
     * 添加封面图片与素材的关联关系
     */
    private void addNewsMaterialByBucketForCover(List<String> contentImageList, WmNews wmNews, WmNewsDto wmNewsDto) {
        //获取封面图片的集合
        List<String> coverImages = wmNewsDto.getImages();

        //判断封面是否为自动生成
        if (wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)) {
            //判断集合是否为空,如果为空，则添加内容图片
            if (CollectionUtils.isEmpty(contentImageList)) {
                //如果内容图片为空，则将封面设置为无图模式（即在关联表中不添加图片）
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            } else if (contentImageList.size() <= 2) {
                //如果内容图片小于等于2.则将封面设置为单图模式
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
            } else {
                //如果图片内容图片大于或等于3张，则设置封面为多图模式
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
                //将内容图片集合截取前三张
                coverImages = contentImageList.stream().limit(3).collect(Collectors.toList());
            }
            //更新文章内容
            updateById(wmNews);
        }
        //调用添加关联表方法，添加素材文章的关联关系
        if (CollectionUtils.isNotEmpty(coverImages)) {
            addNewsMaterialByBucket(coverImages, wmNews.getId(), WemediaConstants.WM_IMAGE_REFERENCE);
        }

    }


    /**
     * 添加文章-素材关联关系
     */
    private void addNewsMaterialByBucket(List<String> listUrl, Integer nid, short type) {
        //判断当前素材集合中的元素在数据库中是否存在
        List<String> list = listUrl.stream().map(str -> str.replaceAll(webSite, "")).collect(Collectors.toList());
        System.out.println("list = " + list);
        LambdaQueryWrapper<WmMaterial> wrapper = Wrappers.lambdaQuery();
        wrapper.in(WmMaterial::getUrl, list)
                .eq(WmMaterial::getUserId, WmThreadLocalUtils.getUser().getId());
        List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(wmMaterials)) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "引用的素材不存在！！！！");
        }
        //获取所有的素材的id
        List<Integer> collectId = wmMaterials.stream()
                .map(wmMaterial -> wmMaterial.getId())
                .collect(Collectors.toList());
        //调用方法执行批量添加操作
        wmNewsMaterialMapper.addNewsMaterialByBucket(collectId, nid, type);
    }

    /**
     * 获取url集合
     */
    private List<String> getUrlLists(WmNews wmNews) {
        //取出content
        String content = wmNews.getContent();
        List<Map> maps = JSONArray.parseArray(content, Map.class);

        //流操作取出
        List<String> collect = maps.stream()
                .filter(map -> WemediaConstants.WM_NEWS_TYPE_IMAGE.equals(map.get("type")))//取出所有的图片
                .map(map -> (String) map.get("value"))//取出所有图片的url
                .map(url -> url.replaceAll(webSite, ""))//取出webSite前缀
                .collect(Collectors.toList());//将其收集为list集合
        System.out.println("collect = " + collect);
        return collect;
    }

    /**
     * 保存或修改文章
     */
    private void saverOrUpdate(WmNews wmNews, WmNewsDto wmNewsDto) {
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable(WemediaConstants.WM_NEWS_UP);//上架
        if (wmNewsDto.getId() == null) {//id为空则保存
            save(wmNews);
        } else {//id存在则修改
            updateById(wmNews);
            //删除文章-素材中间表中的信息，重修添加
            LambdaUpdateWrapper<WmNewsMaterial> wrapper = Wrappers.lambdaUpdate();
            wrapper.eq(WmNewsMaterial::getNewsId, wmNews.getId());
            wmNewsMaterialMapper.delete(wrapper);
        }
    }

    /**
     * 根据文章id查询文章
     */
    @Override
    public ResponseResult findNewById(Integer nid) {
        //判断数据是否合法
        if (nid == null) {
            CustomException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        //执行查询操作
        WmNews news = getById(nid);
        if (news == null) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        ResponseResult result = ResponseResult.okResult(news);
        result.setHost(webSite);
        return result;
    }

    /**
     * 根据文章id删除文章
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseResult deleteNewById(Integer nid) {
        //判断数据是否合法
        if (nid == null) {
            CustomException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        //判断数据库中是否存在当前new
        WmNews wmNews = getById(nid);
        if (wmNews == null) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "当前数据不存在");
        }
        //判断当前文章状态
        if (wmNews.getStatus() == 9) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "当前状态暂不支持删除");
        }
        //删除wm-news表中的相关元素
        removeById(nid);
        //如果是草稿的话则直接返回结果
        if (wmNews.getStatus() == 0) {
            return ResponseResult.okResult();
        }
        //不是草稿则需删除素材文章关联表中的关联关系
        LambdaUpdateWrapper<WmNewsMaterial> wrapper = Wrappers.<WmNewsMaterial>lambdaUpdate().eq(WmNewsMaterial::getNewsId, nid);
        wmNewsMaterialMapper.delete(wrapper);
        return ResponseResult.okResult();
    }

    /**
     * 自媒体文章-上架、下架
     */
    @Override
    public ResponseResult newsUpOrDown(WmNewsDto wmNewsDto) {
        //判断数据是否异常
        if (wmNewsDto == null || wmNewsDto.getEnable() == null || wmNewsDto.getId() == null) {
            CustomException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        Short enable = wmNewsDto.getEnable();
        Integer nid = wmNewsDto.getId();
        //判断当前id的new是否存在
        WmNews wmNews = getById(nid);
        if (wmNews == null) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //判断当前文章状态是否为9（已发布状态）
        if (wmNews.getStatus() != 9) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "当前文章不是发布状态，不能进行上下架操作");
        }
        wmNews.setEnable(enable);
        //文章存在，下架
        if (enable != null && enable > -1 && enable < 2) {
            updateById(wmNews);
        }
        //发送消息通知app端进行文章的上下架操作
        if (wmNews.getArticleId() != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("articleId", wmNews.getArticleId());
            map.put("enable", wmNewsDto.getEnable());
            String message = JSON.toJSONString(map);
            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, message);
        }
        return ResponseResult.okResult();
    }

    /**
     * 查询所有待发布的文章
     */
    @Override
    public ResponseResult findWaitingPublish() {
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.lambdaQuery();
        wrapper.in(WmNews::getStatus, 4, 8)
                .le(WmNews::getPublishTime, new Date())
                .select(WmNews::getId);
        List<WmNews> newsList = list(wrapper);
        System.out.println("newsList = " + newsList);
        List<Integer> idList = newsList.stream().map(wmNews -> wmNews.getId()).collect(Collectors.toList());
        System.out.println("idList = " + idList);
        return ResponseResult.okResult(idList);
    }

    /**
     * 根据状态查询所有文章信息
     */
    @Override
    public ResponseResult findPersonChargeNews(NewsAuthDto dto) {
        // 1. 检查参数    分页    标题
        dto.checkParam();
        Integer currentPage = dto.getPage();
        dto.setPage((currentPage - 1) * dto.getSize());
        // 标题
        if (StringUtils.isNotBlank(dto.getTitle())) {
            dto.setTitle("%" + dto.getTitle() + "%");
        }
        // 2. 调用mapper进行查询
        List<WmNewsVo> listAndPage = wmNewsMapper.findListAndPage(dto);
        for (WmNewsVo wmNewsVo : listAndPage) {
            System.out.println("wmNewsVo = " + wmNewsVo);
            String content = wmNewsVo.getContent();
            System.out.println("content = " + content);
        }
        long listCount = wmNewsMapper.findListCount(dto);
        // 3. 封装分页返回结果
        PageResponseResult responseResult = new PageResponseResult(currentPage, dto.getSize(), listCount);
        responseResult.setData(listAndPage);
        return responseResult;
    }

    /**
     * 根据id查询文章信息
     */
    @Override
    public ResponseResult findOneById(Integer id) {
        if (id == null) {
            CustomException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNewsVo wmNewsVoById = wmNewsMapper.findWmNewsVoById(id);
        return ResponseResult.okResult(wmNewsVoById);
    }

    /**
     * 人工审核后修改文章状态
     */
    @Override
    public ResponseResult updateNewStatus(Short status, NewsAuthDto dto) {
        //判断数据是否合法
        if (dto == null || status == null || dto.getId() == null) {
            CustomException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        //判断数据中是否存在当前数据
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(WmNews::getId, dto.getId());
        WmNews news = getOne(wrapper);
        if (news == null) {
            CustomException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        news.setStatus(status);
        if (StringUtils.isNotBlank(dto.getMsg())) {
            news.setReason(dto.getMsg());
        }
        updateById(news);
        return ResponseResult.okResult();
    }
}
